﻿namespace WasiewiczHomepage.Repositories
{
    using System;
    using System.Collections.Generic;
    using System.Data.Entity;
    using System.Data.Entity.Migrations;
    using System.Linq;
    using System.Linq.Expressions;

    public class Repository<T> : IRepository<T> where T : class
    {
        private readonly DbContext dbContext;
       
        private readonly DbSet<T> dbSet;

        public Repository(DbContext dbContext)
        {
            this.dbContext = dbContext;
            this.dbSet = this.dbContext.Set<T>();
        }

        public T Get(int id)
        {
            return this.dbSet.Find(id);
        }

        public void Delete(T entity)
        {
            this.dbSet.Remove(entity);
        }

        public void Update(T entity)
        {
            this.dbSet.Attach(entity);
            this.dbContext.Entry(entity).State = EntityState.Modified;
        }

        public void Create(T entity)
        {
            this.dbSet.Add(entity);
        }

        public void CreateOrUpdate(T entity)
        {
            var dynamicEntity = (dynamic)entity;

            try
            {
                if (dynamicEntity.ID == 0)
                {
                    this.Create(entity);
                }
                else
                {
                    this.Update(entity);
                }
            }
            catch
            {
                this.dbSet.AddOrUpdate(entity);
            }
        }

        public IEnumerable<T> GetAll()
        {
            return this.dbSet.ToList();
        }

        public IEnumerable<T> Fetch(Expression<Func<T, bool>> predicate)
        {
            return this.dbSet.Where(predicate);
        }

        public IQueryable<T> AsQuerable()
        {
            return this.dbSet.AsQueryable();
        }

        public void Save()
        {
            this.dbContext.SaveChanges();
        }

        public void Delete(IEnumerable<T> entities)
        {
            this.dbSet.RemoveRange(entities);
        }

        public void Evict(T entity)
        {
            this.dbContext.Entry(entity).State = EntityState.Detached;
        }

        public T DynamicInstance()
        {
            return this.dbSet.Create();
        }

        public bool Exists(int id)
        {
            return this.Get(id) != null;
        }
    }
}